﻿using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio.Utilities;
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Design;
using System.IO;

namespace FineUICoreDesigner
{
    [Export(typeof(IVsTextViewCreationListener))]
    [ContentType("htmlx")]
    [TextViewRole(PredefinedTextViewRoles.Editable)]
    [PartNotDiscoverable]
    public class GoToDefinitionHandler : IVsTextViewCreationListener
    {
        private IWpfTextView _textView;
        private IVsTextView _textViewAdapter;

        [Import]
        internal IVsEditorAdaptersFactoryService EditorAdaptersFactoryService { get; set; }

        public void VsTextViewCreated(IVsTextView textViewAdapter)
        {
            IWpfTextView textView = EditorAdaptersFactoryService.GetWpfTextView(textViewAdapter);
        }
    }

    public class GoToDefinitionCommand
    {
        private readonly FineUICoreDesigner _package;
        private IVsTextView _textViewAdapter => GetActiveTextView();
        private IWpfTextView _textView => GetWpfActiveTextView();

        public GoToDefinitionCommand(FineUICoreDesigner package)
        {
            _package = package;

            BaseHelp.OutputLine("方法跳转功能 初始化成功");
        }

        private IWpfTextView GetWpfActiveTextView()
        {
            var componentModel = (IComponentModel)_package.GetServiceAsync(typeof(SComponentModel)).Result;
            var editorAdaptersFactoryService = componentModel.GetService<IVsEditorAdaptersFactoryService>();
            return editorAdaptersFactoryService.GetWpfTextView(_textViewAdapter);
        }

        private IVsTextView GetActiveTextView()
        {
            // 获取当前活动的 IVsTextView 的逻辑
            IVsTextManager textManager = (IVsTextManager)_package.GetServiceAsync(typeof(SVsTextManager)).Result;
            IVsTextView activeTextView = null;
            textManager.GetActiveView(1, null, out activeTextView);
            return activeTextView;
        }

        public void AddCommand(OleMenuCommandService commandService)
        {
            var menuCommandID = new CommandID(new Guid("D38C3F3E-D44C-4A10-AA28-928EC1C6C4C1"), 0x0100);
            var menuItem = new OleMenuCommand(ExecuteGoToDefinition, menuCommandID);
            menuItem.BeforeQueryStatus += MenuItem_BeforeQueryStatus;
            commandService.AddCommand(menuItem);
            var GoToControllerCommandID = new CommandID(new Guid("D38C3F3E-D44C-4A10-AA28-928EC1C6C4C1"), 0x0101);
            var menuGoToController = new OleMenuCommand(ExecuteGoToController, GoToControllerCommandID);
            menuGoToController.BeforeQueryStatus += MenuItem_BeforeQueryStatus2;
            commandService.AddCommand(menuGoToController);
            //BaseHelp.OutputLine("GoToDefinitionCommand 按钮 初始化成功");
        }

        #region 转到控制器

        private void MenuItem_BeforeQueryStatus2(object sender, EventArgs e)
        {
            //BaseHelp.OutputLine("MenuItem_BeforeQueryStatus");
            ThreadHelper.ThrowIfNotOnUIThread();

            var menuCommand = sender as OleMenuCommand;
            var CshtmlFile = new Func<bool>(() =>
            {
                ThreadHelper.ThrowIfNotOnUIThread();
                var dte = _package.GetServiceAsync(typeof(DTE)).Result as DTE2;
                if (dte?.ActiveDocument != null)
                {
                    string fileName = dte.ActiveDocument.FullName;
                    if (fileName.EndsWith(".cshtml", StringComparison.OrdinalIgnoreCase))
                    {
                        string ControllerFilePath = GetControllerFilePath();
                        //文件是否存在
                        if (File.Exists(ControllerFilePath))
                        {
                            return true;
                        }
                    }
                }
                return false;
            });
            //BaseHelp.OutputLine($"IsCshtmlFile {CshtmlFile}");
            if (menuCommand != null)
            {
                menuCommand.Visible = CshtmlFile();
            }
        }

        private void ExecuteGoToController(object sender, EventArgs e)
        {
            //根据 cshtml 文件找到 Controller.cs文件
            if (_textView != null)
            {
                string ControllerFilePath = GetControllerFilePath();
                try
                {
                    var dte = (EnvDTE.DTE)ServiceProvider.GlobalProvider.GetService(typeof(EnvDTE.DTE));
                    var cshtmlCsDocument = dte.Documents.Open(ControllerFilePath);
                    cshtmlCsDocument.Activate();
                    BaseHelp.OutputLine($"跳转到Controller");
                }
                catch { }
            }
        }

        /// <summary>
        /// 获取控制器文件
        /// </summary>
        /// <returns></returns>
        private string GetControllerFilePath()
        {
            var dte = _package.GetServiceAsync(typeof(DTE)).Result as DTE2;
            string cshtmlFilePath = dte.ActiveDocument.FullName;
            string folderName = new DirectoryInfo(Path.GetDirectoryName(cshtmlFilePath)).Name;

            // 获取 .cshtml 文件的上级目录
            string parentDirectory = Directory.GetParent(cshtmlFilePath).FullName;

            // 获取上级目录的上级目录（Views 文件夹所在的目录）
            string viewsParentDirectory = Directory.GetParent(Directory.GetParent(parentDirectory).FullName).FullName;

            // 构建 Controllers 文件夹的路径
            var ControllersFolderPath = Path.Combine(viewsParentDirectory, "Controllers");

            // 构建控制器文件名
            var controllerFileName = folderName + "Controller.cs";
            var CsFileName = controllerFileName;

            var ControllerFilePath = "";
            if (Directory.Exists(ControllersFolderPath))
            {
                //遍历 ControllersFolderPath 下所有文件和子文件夹， 找到控制器文件
                foreach (var file in Directory.EnumerateFiles(ControllersFolderPath, "*", SearchOption.AllDirectories))
                {
                    if (Path.GetFileName(file).Equals(controllerFileName, StringComparison.OrdinalIgnoreCase))
                    {
                        ControllersFolderPath = Directory.GetParent(file).FullName;
                        ControllerFilePath = file;
                        break;
                    }
                }
            }
            // 构建控制器文件的完整路径
            return ControllerFilePath;
        }

        #endregion 转到控制器

        #region 转到方法

        private void MenuItem_BeforeQueryStatus(object sender, EventArgs e)
        {
            //BaseHelp.OutputLine("MenuItem_BeforeQueryStatus");
            ThreadHelper.ThrowIfNotOnUIThread();

            var menuCommand = sender as OleMenuCommand;
            var CshtmlFile = IsCshtmlFile();
            //BaseHelp.OutputLine($"IsCshtmlFile {CshtmlFile}");
            if (menuCommand != null)
            {
                menuCommand.Visible = CshtmlFile;
            }

            //var dte = _package.GetServiceAsync(typeof(DTE)).Result as DTE2;
            //var contextGuids = dte?.ActiveDocument.ActiveWindow.ContextAttributes;
            //foreach (ContextAttribute context in contextGuids)
            //{
            //    BaseHelp.OutputLine($"GoToDefinitionCommand 按钮 初始化成功 {context.Name} - {context.Values}");
            //    //ystem.Diagnostics.Debug.WriteLine($"Context GUID: {context.Name} - {context.Values}");
            //}
        }

        private bool IsCshtmlFile()
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var dte = _package.GetServiceAsync(typeof(DTE)).Result as DTE2;
            if (dte?.ActiveDocument != null)
            {
                string fileName = dte.ActiveDocument.FullName;
                if (fileName.EndsWith(".cshtml", StringComparison.OrdinalIgnoreCase))
                {
                    if (_textView != null)
                    {
                        var caretPosition = _textView.Caret.Position.BufferPosition;
                        var line = caretPosition.GetContainingLine();
                        var lineText = line.GetText();

                        // 提取方法名
                        var methodName = GetMethodNameUnderCaret(lineText, caretPosition.Position - line.Start.Position);
                        if (!string.IsNullOrEmpty(methodName))
                        {
                            return true;
                        }
                    }
                }
            }

            return false;
        }

        private void ExecuteGoToDefinition(object sender, EventArgs e)
        {
            if (_textView != null)
            {
                var caretPosition = _textView.Caret.Position.BufferPosition;
                var line = caretPosition.GetContainingLine();
                var lineText = line.GetText();

                // 提取方法名
                var methodName = GetMethodNameUnderCaret(lineText, caretPosition.Position - line.Start.Position);
                if (!string.IsNullOrEmpty(methodName))
                {
                    // 查找对应的 .cshtml.cs 文件和方法
                    var cshtmlFilePath = _textView.TextBuffer.Properties.GetProperty<ITextDocument>(typeof(ITextDocument)).FilePath;
                    var cshtmlCsFilePath = cshtmlFilePath.Replace(".cshtml", ".cshtml.cs");
                    if (cshtmlCsFilePath == null)
                    {
                        BaseHelp.OutputLine("没有找到 .cshtml.cs 文件");
                        return;
                    }
                    try
                    {
                        var dte = (EnvDTE.DTE)ServiceProvider.GlobalProvider.GetService(typeof(EnvDTE.DTE));
                        var cshtmlCsDocument = dte.Documents.Open(cshtmlCsFilePath);
                        var cshtmlCsTextSelection = cshtmlCsDocument.Selection as EnvDTE.TextSelection;

                        // 查找方法
                        cshtmlCsTextSelection?.GotoLine(1);
                        if (cshtmlCsTextSelection?.FindText($"{methodName}(object sender") ?? false)
                        {
                            cshtmlCsTextSelection?.FindText($"{methodName}Async(object sender");
                        };

                        cshtmlCsDocument.Activate();
                        BaseHelp.OutputLine($"跳转到方法: {methodName}");
                    }
                    catch { }
                }
                else
                {
                    //BaseHelp.OutputLine("没有找到方法");
                }
            }
        }

        private string GetMethodNameUnderCaret(string lineText, int caretPositionInLine)
        {
            // 简单的提取 OnClick="btnEnable_Click" 中的方法名
            var onclickIndex = lineText.IndexOf("OnClick=\"", StringComparison.OrdinalIgnoreCase);
            if (onclickIndex >= 0)
            {
                var startIndex = onclickIndex + "OnClick=\"".Length;
                var endIndex = lineText.IndexOf("\"", startIndex, StringComparison.Ordinal);
                if (endIndex > startIndex)
                {
                    var methodName = lineText.Substring(startIndex, endIndex - startIndex);
                    var methodIndex = lineText.IndexOf(methodName, StringComparison.Ordinal);
                    if (methodIndex <= caretPositionInLine && methodIndex + methodName.Length >= caretPositionInLine)
                    {
                        return methodName;
                    }
                }
            }
            return null;
        }

        #endregion 转到方法
    }
}
